#include "HzThreadPool.h"


ThreadWorker::ThreadWorker(FunPtr func, void *arg):arg(arg)
{
    if (func == NULL)
    {
        std::cerr << "Error: fun is empty." << std::endl;
        funptr = NULL;
        return;
    }

    funptr = [func](void *arg)->int
    {  return func(arg); };
}

int ThreadWorker::operator()()
{
    if (IsValid())
    {
        int ret = funptr(arg);
        return ret;
    }
    return -1;
}

bool ThreadWorker::IsValid() const
{
    return funptr != NULL;
}

bool Thread::Start()
{
    m_bStatus = true;
    // 创建线程
    m_thread = std::thread(&Thread::Work, this);
    return m_bStatus;
}

bool Thread::Stop()
{
    // 线程未被创建
    if (m_bStatus == false){
        return true;
    }
    m_bStatus = false;
    // 判断当前线程是否在工作,没有工作就唤醒
    if (IsIdle() == false)
    {
        // 唤醒线程
        cv.notify_one();
    }
    // 等待线程执行结束，回收线程
    m_thread.join();
    return true;
}

Thread::Thread(HzThreadPool *pool) : pool(pool)
{
    m_worker.store(NULL);
    m_bStatus = false;
}

void Thread::Work()
{
    std::unique_lock<std::mutex> lock(mtx);
    while (m_bStatus)
    {
        // 进入休眠等待被唤醒   ,   释放mtx
        cv.wait(lock);
        // 唤醒后开行执行
        //  1 检测m_worker是否为空
        if (m_worker == NULL)
        {
            continue;
        }
        // 2 加载函数
        ThreadWorker *worker = m_worker.load();
        // 3 检查m_worker是否有效，有效就执行
        if (worker->IsValid())
        {
            int ret = (*worker)();
            if (ret == -1)
            {
                std::cout << "thread found warning" << std::endl;
            }
            else
            {
                // 执行完后，置空
                delete worker;
                m_worker.store(NULL);
                // 加入到空闲队列
                pool->m_push_lock.lock();
                pool->freeThreads.push(this);
                pool->m_push_lock.unlock();
            }
        }
    }
}

bool Thread::IsIdle()
{
    if (m_worker.load() == NULL)
        return false;
    return true;
}


void Thread::UpdateWorker(ThreadWorker *worker)
{
    // 判断线程是否正在工作
    if (m_worker.load() != NULL)
        return;
    // 判断这个工作者是否有效
    if (!worker->IsValid())
        return;
    // 更新工作者
    m_worker.store(worker);
    // 唤醒线程
    cv.notify_one();
}

HzThreadPool::HzThreadPool() {}

HzThreadPool::HzThreadPool(int size) : size(size)
{
    threads.resize(size);
    for (size_t i = 0; i < size; i++)
    {
        threads[i] = new Thread(this);
    }
}

HzThreadPool::~HzThreadPool()
{
    Stop();
    for (size_t i = 0; i < threads.size(); i++)
    {
        Thread *pThread = threads[i];
        threads[i] = NULL;
        delete pThread;
    }
    threads.clear();
}

bool HzThreadPool::Invoke()
{
    bool ret = true;
    for (size_t i = 0; i < threads.size(); i++)
    {
        // 开启线程
        if (threads[i]->Start() == false)
        {
            ret = false;
            break;
        }
        // 将线程加入到空闲队列
        freeThreads.push(threads[i]);
    }
    if (ret == false)
    {
        for (size_t i = 0; i < threads.size(); i++)
        {
            threads[i]->Stop();
        }
        while(freeThreads.size()) freeThreads.pop();
    }
    return ret;
}

void HzThreadPool::Stop()
{
    for (size_t i = 0; i < threads.size(); i++)
    {
        threads[i]->Stop();
    }
    while (freeThreads.size())
    {
        freeThreads.pop();
    }
}

Thread *HzThreadPool::DispatchWorker(ThreadWorker *worker)
{
    m_lock.lock();
    // 取出空闲队列里的一个线程
    if (freeThreads.size() == 0)
    {
        m_lock.unlock();
        return NULL;
    }
    Thread *thizthread = freeThreads.front();
    thizthread->UpdateWorker(worker);
    freeThreads.pop();
    m_lock.unlock();
    return thizthread;
}
